/**
 * @author Kenneth
 *
 */
package hk.edu.polyu.comp.motioncapture;

import hk.edu.polyu.comp.motioncapture.point.*;

import java.util.Iterator;
import java.util.Date;

// import analysis.geometry.OptiPo;;

public class CoordinateOperation extends CameraControl {

	int currentPointCounter = 0;
	int currentPointCounter1 = 0;
	int lastPointCounter = 0;
	int lastPointCounter1 = 0;

	private CameraControl cc;
	private FPS fps;

	/**
	 * Create an camera object
	 * 
	 * @param point -
	 *            Accept Point Recognition
	 * @param sound -
	 *            Accept Speech Recognition
	 */
	public CoordinateOperation(boolean point, boolean sound, Screen screen) {
		cc = new CameraControl(point, sound, screen);
		fps = new FPS(cc);
	}

	public void start() {
		cc.start();
		fps.start();
	}

	/**
	 * Prints out all the coordinates.
	 */
	public void printAllResult() {
		// print out the result
		Iterator<Frame> it = cc.getPlayer().iterator();

		while (it.hasNext()) {
			Point[] result = it.next().getPointArray();

			for (int i = 0; i < result.length; i++)
				System.out.print("X: " + result[i].getX() + "Y: "
						+ result[i].getY() + "    ");
			System.out.println("");
		}
	}

	/**
	 * Gets all the coordinates.
	 * 
	 * @return A vector representing all the coordinates sort by the frame
	 *         number. Each vector store an array with the type of
	 *         motioncapture.point.OptiPoint.
	 */
	public FrameSet returnAllResult() {
		return cc.getPlayer();
	}

	/**
	 * Gets all the coordinates.
	 * 
	 * @return A vector representing all the coordinates sort by the frame
	 *         number within a time Each vector store an array with the type of
	 *         motioncapture.point.OptiPoint.
	 */
	public FrameSet returnTimeResult(double second) {
		FrameSet result = new FrameSet(120, 120);
		Double numberOfPointDouble = getAverageFPS() * second;
		int numberOfPoint = numberOfPointDouble.intValue();
		int endPointIndex, startPointIndex;

		if (cc.getPlayer().size() < numberOfPoint) {
			endPointIndex = cc.getPlayer().size();
			startPointIndex = 0;
		} else {
			endPointIndex = cc.getPlayer().size();
			startPointIndex = endPointIndex - numberOfPoint;
		}

		for (int i = startPointIndex; i < endPointIndex; i++)
			result.add(cc.getPlayer().frameAt(i));

		return result;
	}
	
	/**
	 * Gets all the coordinates.
	 * 
	 * @return A vector representing all the coordinates sort by the frame
	 *         number within a time Each vector store an array with the type of
	 *         motioncapture.point.OptiPoint.
	 */
	public FrameSet returnFrameResult(int noOfFrame) {
		FrameSet result = new FrameSet(120, 120);
		
		if(cc.getPlayer().size()>noOfFrame)
		{
			for(int i=noOfFrame; i>0;i--)
				result.add(cc.getPlayer().frameAt(cc.getPlayer().size() - i ));
		}else
		{
			for(int i=cc.getPlayer().size()-1; i<0; i++)
				result.add(cc.getPlayer().frameAt(cc.getPlayer().size()));			
		}
		return result;
	}

	/**
	 * Gets the last coordinates.
	 * 
	 * @return A motioncapture.point.OptiPoint vector representing the last
	 *         coordinate.
	 */
	public Frame returnLastResult(boolean returnRepeat) {
		if (returnRepeat) {
			if (!cc.getPlayer().isEmpty()) {
				lastPointCounter1 = cc.getPlayer().size();
				return cc.getPlayer().last();
			} else
				return null;
		} else {

			if (!cc.getPlayer().isEmpty()
					&& lastPointCounter1 < cc.getPlayer().size()) {
				lastPointCounter1 = cc.getPlayer().size();
				return cc.getPlayer().last();
			} else
				return null;
		}
	}
	
	/**
	 * Gets the last coordinates.
	 * 
	 * @return A motioncapture.point.OptiPoint vector representing the last
	 *         coordinate.
	 */
	public FrameSet[] returnLastResultDividedByHoz(double second, int precentage, Screen screen) {
		FrameSet allFreamSet = returnTimeResult(second);
		FrameSet[] result = new FrameSet[2];
		
		double x = screen.getTopRightPoint().getX() - screen.getTopLeftPoint().getX();
		x = (x * precentage / 100) + screen.getTopLeftPoint().getX();
		
		System.out.println(screen.getTopLeftPoint().getX() + "  " + screen.getTopRightPoint().getX() + "  " + x);
		// >x
		result[0] = new FrameSet(120,10);
		// <=x
		result[1] = new FrameSet(120,10);
		
		for(int j=0; j<allFreamSet.size(); j++)
		{
			Frame currentFrame = allFreamSet.frameAt(j);
			Frame frame1 = new Frame();
			Frame frame2 = new Frame();
			
			for(int i=0; i<currentFrame.size(); i++)
			{
				if(currentFrame.pointAt(i).getX()<x)					
					frame1.add(currentFrame.pointAt(i));
				else
					frame2.add(currentFrame.pointAt(i));
			}
			
			result[0].add(frame1);
			result[1].add(frame2);
		}
		
		return result;
	}

	/**
	 * Gets the last coordinates.
	 * 
	 * @return A vector representing the first coordinate sort by the frame
	 *         number. The vector store an array with the type of Point.Double.
	 */
	public Frame returnFirstResult() {
		// Iterator<OptiFrame> e = cc.getPlayer().iterator();
		// return e.next();
		return cc.getPlayer().first();
	}

	public Frame returnNextResult() {

		Frame result = null;
		if (!cc.getPlayer().isEmpty()
				&& cc.getPlayer().size() > currentPointCounter) {
			result = cc.getPlayer().frameAt(currentPointCounter);
			// System.out.println("X: " + result[0].getX() + " Y: " +
			// result[0].getY());
			currentPointCounter++;
			return result;
		} else
			return null;
	}

	public int getFPS() {
		return fps.getFPS();
	}

	public int getAverageFPS() {
		// System.out.print(cc.getFrameSet().size() + " " +
		// startTime.getTime());
		try {
			Date now = new Date();

			int diff = (int) ((now.getTime() - cc.startTime.getTime()) / 1000);
			return (int) (cc.getPlayer().size() / diff);
		} catch (ArithmeticException ae) {
			return 0;
		} catch (NullPointerException npe) {
			return 0;
		}
	}

	public int getRunTime() {
		try {
			Date now = new Date();
			int diff = (int) (now.getTime() - cc.startTime.getTime());
			return diff;

		} catch (NullPointerException npe) {
			return 0;
		}

	}

	public boolean hasSoundCommand() {
		return cc.hasSoundCommand;
	}

	public String getSoundCommand() {
		return cc.soundCommand;
	}
}